home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / avr32 / include / asm / atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  5.0 KB  |  202 lines

  1. /*
  2.  * Atomic operations that C can't guarantee us.  Useful for
  3.  * resource counting etc.
  4.  *
  5.  * But use these as seldom as possible since they are slower than
  6.  * regular operations.
  7.  *
  8.  * Copyright (C) 2004-2006 Atmel Corporation
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License version 2 as
  12.  * published by the Free Software Foundation.
  13.  */
  14. #ifndef __ASM_AVR32_ATOMIC_H
  15. #define __ASM_AVR32_ATOMIC_H
  16.  
  17. #include <asm/system.h>
  18.  
  19. typedef struct { volatile int counter; } atomic_t;
  20. #define ATOMIC_INIT(i)  { (i) }
  21.  
  22. #define atomic_read(v)        ((v)->counter)
  23. #define atomic_set(v, i)    (((v)->counter) = i)
  24.  
  25. /*
  26.  * atomic_sub_return - subtract the atomic variable
  27.  * @i: integer value to subtract
  28.  * @v: pointer of type atomic_t
  29.  *
  30.  * Atomically subtracts @i from @v. Returns the resulting value.
  31.  */
  32. static inline int atomic_sub_return(int i, atomic_t *v)
  33. {
  34.     int result;
  35.  
  36.     asm volatile(
  37.         "/* atomic_sub_return */\n"
  38.         "1:    ssrf    5\n"
  39.         "    ld.w    %0, %2\n"
  40.         "    sub    %0, %3\n"
  41.         "    stcond    %1, %0\n"
  42.         "    brne    1b"
  43.         : "=&r"(result), "=o"(v->counter)
  44.         : "m"(v->counter), "rKs21"(i)
  45.         : "cc");
  46.  
  47.     return result;
  48. }
  49.  
  50. /*
  51.  * atomic_add_return - add integer to atomic variable
  52.  * @i: integer value to add
  53.  * @v: pointer of type atomic_t
  54.  *
  55.  * Atomically adds @i to @v. Returns the resulting value.
  56.  */
  57. static inline int atomic_add_return(int i, atomic_t *v)
  58. {
  59.     int result;
  60.  
  61.     if (__builtin_constant_p(i) && (i >= -1048575) && (i <= 1048576))
  62.         result = atomic_sub_return(-i, v);
  63.     else
  64.         asm volatile(
  65.             "/* atomic_add_return */\n"
  66.             "1:    ssrf    5\n"
  67.             "    ld.w    %0, %1\n"
  68.             "    add    %0, %3\n"
  69.             "    stcond    %2, %0\n"
  70.             "    brne    1b"
  71.             : "=&r"(result), "=o"(v->counter)
  72.             : "m"(v->counter), "r"(i)
  73.             : "cc", "memory");
  74.  
  75.     return result;
  76. }
  77.  
  78. /*
  79.  * atomic_sub_unless - sub unless the number is a given value
  80.  * @v: pointer of type atomic_t
  81.  * @a: the amount to add to v...
  82.  * @u: ...unless v is equal to u.
  83.  *
  84.  * If the atomic value v is not equal to u, this function subtracts a
  85.  * from v, and returns non zero. If v is equal to u then it returns
  86.  * zero. This is done as an atomic operation.
  87. */
  88. static inline int atomic_sub_unless(atomic_t *v, int a, int u)
  89. {
  90.     int tmp, result = 0;
  91.  
  92.     asm volatile(
  93.         "/* atomic_sub_unless */\n"
  94.         "1:    ssrf    5\n"
  95.         "    ld.w    %0, %3\n"
  96.         "    cp.w    %0, %5\n"
  97.         "    breq    1f\n"
  98.         "    sub    %0, %4\n"
  99.         "    stcond    %2, %0\n"
  100.         "    brne    1b\n"
  101.         "    mov    %1, 1\n"
  102.         "1:"
  103.         : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
  104.         : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result)
  105.         : "cc", "memory");
  106.  
  107.     return result;
  108. }
  109.  
  110. /*
  111.  * atomic_add_unless - add unless the number is a given value
  112.  * @v: pointer of type atomic_t
  113.  * @a: the amount to add to v...
  114.  * @u: ...unless v is equal to u.
  115.  *
  116.  * If the atomic value v is not equal to u, this function adds a to v,
  117.  * and returns non zero. If v is equal to u then it returns zero. This
  118.  * is done as an atomic operation.
  119. */
  120. static inline int atomic_add_unless(atomic_t *v, int a, int u)
  121. {
  122.     int tmp, result;
  123.  
  124.     if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576))
  125.         result = atomic_sub_unless(v, -a, u);
  126.     else {
  127.         result = 0;
  128.         asm volatile(
  129.             "/* atomic_add_unless */\n"
  130.             "1:    ssrf    5\n"
  131.             "    ld.w    %0, %3\n"
  132.             "    cp.w    %0, %5\n"
  133.             "    breq    1f\n"
  134.             "    add    %0, %4\n"
  135.             "    stcond    %2, %0\n"
  136.             "    brne    1b\n"
  137.             "    mov    %1, 1\n"
  138.             "1:"
  139.             : "=&r"(tmp), "=&r"(result), "=o"(v->counter)
  140.             : "m"(v->counter), "r"(a), "ir"(u), "1"(result)
  141.             : "cc", "memory");
  142.     }
  143.  
  144.     return result;
  145. }
  146.  
  147. /*
  148.  * atomic_sub_if_positive - conditionally subtract integer from atomic variable
  149.  * @i: integer value to subtract
  150.  * @v: pointer of type atomic_t
  151.  *
  152.  * Atomically test @v and subtract @i if @v is greater or equal than @i.
  153.  * The function returns the old value of @v minus @i.
  154.  */
  155. static inline int atomic_sub_if_positive(int i, atomic_t *v)
  156. {
  157.     int result;
  158.  
  159.     asm volatile(
  160.         "/* atomic_sub_if_positive */\n"
  161.         "1:    ssrf    5\n"
  162.         "    ld.w    %0, %2\n"
  163.         "    sub    %0, %3\n"
  164.         "    brlt    1f\n"
  165.         "    stcond    %1, %0\n"
  166.         "    brne    1b\n"
  167.         "1:"
  168.         : "=&r"(result), "=o"(v->counter)
  169.         : "m"(v->counter), "ir"(i)
  170.         : "cc", "memory");
  171.  
  172.     return result;
  173. }
  174.  
  175. #define atomic_xchg(v, new)    (xchg(&((v)->counter), new))
  176. #define atomic_cmpxchg(v, o, n)    (cmpxchg(&((v)->counter), (o), (n)))
  177.  
  178. #define atomic_sub(i, v)    (void)atomic_sub_return(i, v)
  179. #define atomic_add(i, v)    (void)atomic_add_return(i, v)
  180. #define atomic_dec(v)        atomic_sub(1, (v))
  181. #define atomic_inc(v)        atomic_add(1, (v))
  182.  
  183. #define atomic_dec_return(v)    atomic_sub_return(1, v)
  184. #define atomic_inc_return(v)    atomic_add_return(1, v)
  185.  
  186. #define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0)
  187. #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
  188. #define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
  189. #define atomic_add_negative(i, v) (atomic_add_return(i, v) < 0)
  190.  
  191. #define atomic_inc_not_zero(v)    atomic_add_unless(v, 1, 0)
  192. #define atomic_dec_if_positive(v) atomic_sub_if_positive(1, v)
  193.  
  194. #define smp_mb__before_atomic_dec()    barrier()
  195. #define smp_mb__after_atomic_dec()    barrier()
  196. #define smp_mb__before_atomic_inc()    barrier()
  197. #define smp_mb__after_atomic_inc()    barrier()
  198.  
  199. #include <asm-generic/atomic.h>
  200.  
  201. #endif /*  __ASM_AVR32_ATOMIC_H */
  202.